package tools

import (
	"context"
	"testing"

	malysisv1pb "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/malysis/v1"
	mcpgo "github.com/mark3labs/mcp-go/mcp"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"

	"github.com/safedep/vet/mcp"
)

func TestPackageMalwareTool_ExecuteCheckPackageMalware(t *testing.T) {
	tests := []struct {
		name             string
		requestArgs      map[string]interface{}
		setupDriver      func(*MockDriver)
		expectedContains string
		expectedError    string
	}{
		{
			name: "successful malware report retrieval",
			requestArgs: map[string]interface{}{
				"purl": "pkg:npm/express@4.17.1",
			},
			setupDriver: func(driver *MockDriver) {
				report := &malysisv1pb.Report{
					ReportId: "test-report-123",
					Inference: &malysisv1pb.Report_Inference{
						IsMalware: false,
						Summary:   "Package appears safe",
					},
				}
				driver.On("GetPackageVersionMalwareReport", mock.Anything, mock.AnythingOfType("*packagev1.PackageVersion")).
					Return(report, nil)
			},
			expectedContains: "test-report-123",
			expectedError:    "",
		},
		{
			name:        "missing purl parameter",
			requestArgs: map[string]interface{}{},
			setupDriver: func(driver *MockDriver) {
				// No setup needed as this test will fail before calling the driver
			},
			expectedContains: "",
			expectedError:    "purl is required",
		},
		{
			name: "invalid purl format",
			requestArgs: map[string]interface{}{
				"purl": "invalid-purl-format",
			},
			setupDriver: func(driver *MockDriver) {
				// No setup needed as this test will fail during purl parsing
			},
			expectedContains: "",
			expectedError:    "invalid purl",
		},
		{
			name: "package not found error - graceful handling",
			requestArgs: map[string]interface{}{
				"purl": "pkg:npm/nonexistent@1.0.0",
			},
			setupDriver: func(driver *MockDriver) {
				driver.On("GetPackageVersionMalwareReport", mock.Anything, mock.AnythingOfType("*packagev1.PackageVersion")).
					Return((*malysisv1pb.Report)(nil), mcp.ErrMaliciousPackageScanningPackageNotFound)
			},
			expectedContains: "No known malware found for this package",
			expectedError:    "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Create mocks
			mockDriver := NewMockDriver()
			request := createCallToolRequest("get_package_version_malware_report", tt.requestArgs)

			// Setup driver mock
			tt.setupDriver(mockDriver)

			// Create tool instance
			tool := NewPackageMalwareTool(mockDriver)

			// Execute the method
			result, err := tool.executeCheckPackageMalware(context.Background(), request)

			// Verify results
			if tt.expectedError != "" {
				require.Error(t, err)
				assert.Contains(t, err.Error(), tt.expectedError)
				assert.Nil(t, result)
			} else {
				require.NoError(t, err)
				require.NotNil(t, result)

				// Check that the result is valid and contains expected data
				if tt.expectedContains != "" {
					assert.False(t, result.IsError)
					assert.Len(t, result.Content, 1)
					// Basic validation that we got a proper result
					expectedResult := mcpgo.NewToolResultText(tt.expectedContains)
					assert.Equal(t, expectedResult.IsError, result.IsError)
					assert.Len(t, result.Content, len(expectedResult.Content))
				}
			}

			// Verify driver expectations were met
			mockDriver.AssertExpectations(t)
		})
	}
}

func TestPackageMalwareTool_Register(t *testing.T) {
	mockDriver := NewMockDriver()
	tool := NewPackageMalwareTool(mockDriver)

	assert.NotNil(t, tool)
	assert.Equal(t, mockDriver, tool.driver)
}
